#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <vector>

using namespace std;
using LL = long long;
const int N = 2010;

/*
through the test we can know that for n (1 <= n <= 1000) satisfies the condition below:
n + n / 2 >= lower_bound(n)

so we can construct a graph easily based on this condition

*/

int p;
int primes[N], cnt;
bool st[N];
bool ok[N];
int n;

void get_primes(int n){
    for(int i = 2; i <= n; i ++){
        if(!st[i]){
            primes[cnt ++] = i;
        }

        for(int j = 0; primes[j] <= n / i; j ++){
            st[i * primes[j]] = true;
            if(i % primes[j] == 0) break;
        }
    }
}

int f(int x){
    int l = 0, r = cnt - 1;
    while(l < r){
        int mid = l + r >> 1;
        if(primes[mid] >= x) r = mid;
        else l = mid + 1;
    }

    return l;
}

int main(){
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    get_primes(1100);

    cin >> p;

    int t = primes[f(p)] - p;
    cout << primes[f(p)] << '\n';
    for(int i = 1; i + 1 <= p; i ++){
        cout << i << " " << i + 1 << '\n';
    }
    cout << p << " " << 1 << '\n';
   
    for(int i = 1; i + 2 <= p && t; i ++){
        if(!ok[i] && !ok[i + 2]){
            cout << i << " " << i + 2 << '\n';
            ok[i] = ok[i + 2] = true;
            t --;
        }

        // if(st[4]) cout << i << '\n';
    }

   // cout << "i = 2 : " << st[2] << " " << st[4] << '\n';

    return 0;
}